<?php
/**
 * Base class
 *
 * Standard base class containing basale functions in MySQLcompare
 *
 * PHP version 5
 *
 * Copyright (C) 2012 Ewald van Gemert (ewald@vangee.nl)
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
 * associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
 * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 
 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * @category   Development tool
 * @package    MySQLcompare
 * @author     Ewald van Gemert <ewald@vangee.nl>
 * @license    MIT 3
 * @version    SVN: 
 * @link       http://code.google.com/p/mysqlcompare
 * @since      File available since Release 0.9
 */

require_once 'htmlresult.class.php';

// ###########################################################################
// Base class
// ###########################################################################
class COMPAREBASE {
	protected $dba = null;
	protected $dbb = null;
	protected $tablesa = array();
	protected $tablesb = array();
	protected $tablesc = array(); // All unique table names (a OR b)
	protected $colsa = array();
	protected $colsb = array();
	protected $colsc = array();   // All unique column names (a OR b)
	protected $colsi = array();   // Intersect column names (a AND b)
	protected $possibleKeys = array();
	protected $primaryKeys = array();
	/* result of tabledatacompare */
	protected $rowsDiff = array();
	protected $rowsIdent = array();
	protected $rowsRecA = array();
	protected $rowsRecB = array();
	
	// HTML object
	protected $html = null;	
	
	// ***********************************************************************
	// public functions
	// ***********************************************************************
	public function __construct($srv, $sdba, $sdbb, $silent=false) {
		//ob_start();
		global $setting;
		list($srva, $dba) = explode(".", $sdba);
		list($srvb, $dbb) = explode(".", $sdbb);
		
		if (isset($srv->servers[$srva])) {
			$this->dba = new SRVITEM($srv->servers[$srva]->getfilecontent(), $setting, 'dba');
			$this->dba->dbuse($dba);
			$this->tablesa = $this->dba->gettables($dba);		
		}
		if (isset($srv->servers[$srvb])) {
			$this->dbb = new SRVITEM($srv->servers[$srvb]->getfilecontent(), $setting, 'dbb');
			$this->dbb->dbuse($dbb);
			$this->tablesb = $this->dbb->gettables($dbb);		
		}

		// Create total tables list (c)
		$this->tablesc = array_unique(array_merge($this->tablesa, $this->tablesb));
		sort($this->tablesc);
		
		$this->html = new HTMLRESULT();
	}
	
	public function __destroy() {
		// Maybe close some connections and free some objects?
		//if (ob_get_length()==false) echo ob_get_clean();
	}
	
	public function metaCompare($metaA, $metaB) {
		$metaIntersect = array();
		$this->primaryKeys = array();
		$this->possibleKeys = array();
		$this->colsa = array();
		$this->colsb = array();
		foreach ($metaA as $meta) $this->colsa[] = $meta->name;
		foreach ($metaB as $meta) {
			$this->colsb[] = $meta->name;
			if (isset($metaA[$meta->name])) $metaIntersect[$meta->name] = $meta;
			if ($meta->primary_key==1) $this->primaryKeys[] = $meta->name;
			if (($meta->blob==0)&&(count($this->possibleKeys)<12)) $this->possibleKeys[] = $meta->name;
		}
		$this->possibleKeys = array_unique(array_merge($this->primaryKeys, $this->possibleKeys));
		$this->colsc = array_unique(array_merge($this->colsa, $this->colsb));
		$this->colsi = array_intersect($this->colsa, $this->colsb);
		return $metaIntersect; // Return meta data Intersect (that is existing in A and exists in B)
	}

	public function setTblFilter($filter) {
		$this->tblFilter = $filter;
	}
	
	public function diff($old, $new){
		$maxlen = '';
		foreach($old as $oindex => $ovalue){
			$nkeys = array_keys($new, $ovalue);
			foreach($nkeys as $nindex){
				$matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ?
					$matrix[$oindex - 1][$nindex - 1] + 1 : 1;
				if($matrix[$oindex][$nindex] > $maxlen){
					$maxlen = $matrix[$oindex][$nindex];
					$omax = $oindex + 1 - $maxlen;
					$nmax = $nindex + 1 - $maxlen;
				}
			}	
		}
		if($maxlen == 0) return array(array('d'=>$old, 'i'=>$new));
		return array_merge(
			$this->diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
			array_slice($new, $nmax, $maxlen),
			$this->diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
	}

	public function htmlDiff($old, $new){
		$ret = '';
		$diff = $this->diff(explode(' ', $old), explode(' ', $new));
		foreach($diff as $k){
			if(is_array($k))
				$ret .= (!empty($k['d'])?"<del>".implode(' ',$k['d'])."</del> ":'').
					(!empty($k['i'])?"<ins>".implode(' ',$k['i'])."</ins> ":'');
			else $ret .= $k . ' ';
		}
		return $ret;
	}

	// Compare 2 set's of table-records
	// Result: - $this->rowsDiff    : array of different records
	//         - $this->rowsIdent   : array of identical records
	//         - $this->rowsRecA    : array of records only existing in A
	//         - $this->rowsRecB    : array of records only existing in B
	public function compareTableData($objTableA, $objTableB){
		// Clear all first
		$this->rowsDiff=array();
		$this->rowsIdent=array();
		$this->rowsRecA=array();
		$this->rowsRecB = $objTableB;
		// Loop door de ene lijst heen, en zoek de andere
		foreach ($objTableA as $keyA => $arr) {
			if (isset($objTableB[$keyA])) {
				if ($objTableB[$keyA]['chk']==$arr['chk']) {
					$rowa = $arr['row'];
					$key = $arr['keys'];
					$this->rowsIdent[] = array('keys' => $key, 'row' => $rowa);
				} else {
					$this->rowsDiff[] = array(
							  'keys' => $arr['keys']
							, 'rowa' => $arr['row']
							, 'rowb' => $objTableB[$keyA]['row']
							, 'sel' => $arr['sel']);
				}
				unset($this->rowsRecB[$keyA]);
			} else {
				$rowa = $arr['row'];
				$key = $arr['keys'];
				$this->rowsRecA[] = array('keys' => $key, 'row' => $rowa);
			}
		}
	}

	public function compareTableRow($rowA, $rowB, $metaA, $metaB){
		$result = array();
		$cols = array_unique(array_merge(array_keys($rowA),array_keys($rowB)));
		foreach ($cols as $col) {
			if (isset($rowA[$col])) {
				$a = $rowA[$col];
				$charsetA = mb_detect_encoding($a, "ISO-8859-1, UTF-8, ASCII, UTF-7");
				$lenA = mb_strlen($a, $charsetA);
			} else {
				$a = $charsetA = $lenA = "";
			}
			if (isset($rowB[$col])) {
				$b = $rowB[$col];
				$charsetB = mb_detect_encoding($b, "ISO-8859-1, UTF-8, ASCII, UTF-7");
				$lenB = mb_strlen($b, $charsetB);
			} else {
				$b = $charsetB = $lenB = "";
			}
			// Please check this via Meta data, and add new display types.
			$type = ((strpos("{$a}{$b}","\n")===false)&&(strlen($a)<80)&&(strlen($b)<80)) ? "input" : "text";
			
			$result[] = array(	'fieldA' => $a
							  , 'fieldB' => $b
							  , 'type' => $type
							  , 'colnam' => $col
							  , 'charsA' => strlen($a)
							  , 'charsB' => strlen($b)
							  , 'sizeA' => $lenA
							  , 'sizeB' => $lenB
							  , 'charsetA' => $charsetA
							  , 'charsetB' => $charsetB
			);
		}
		return $result;
	}

}

